package me.zhengjie.modules.vip.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import me.zhengjie.modules.system.domain.DictDetail;
import me.zhengjie.modules.system.service.DictDetailService;
import me.zhengjie.modules.vip.domain.MemberCards;
import me.zhengjie.modules.vip.domain.MemberLevels;
import me.zhengjie.modules.vip.domain.Members;
import me.zhengjie.modules.vip.domain.RechargeRecord;
import me.zhengjie.modules.vip.mapper.MembersMapper;
import me.zhengjie.modules.vip.service.MemberLevelsService;
import me.zhengjie.modules.vip.service.RechargeRecordService;
import me.zhengjie.utils.FileUtil;
import lombok.RequiredArgsConstructor;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import me.zhengjie.modules.vip.service.MemberCardsService;
import me.zhengjie.modules.vip.domain.vo.MemberCardsQueryCriteria;
import me.zhengjie.modules.vip.mapper.MemberCardsMapper;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.SecurityUtils;

import java.util.List;
import java.util.Map;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import me.zhengjie.utils.PageResult;
import java.math.BigDecimal;
import me.zhengjie.modules.vip.domain.dto.RechargeDTO;
import me.zhengjie.exception.BadRequestException;
import java.util.Optional;
import java.util.stream.Collectors;

/**
* @description 服务实现
* @author ck
* @date 2024-12-27
**/
@Service
@RequiredArgsConstructor
public class MemberCardsServiceImpl extends ServiceImpl<MemberCardsMapper, MemberCards> implements MemberCardsService {

    private final DictDetailService dictDetailService;
    private final RechargeRecordService rechargeRecordService;
    private final MemberCardsMapper memberCardsMapper;
    private final MembersMapper membersMapper;
    private final MemberLevelsService memberLevelsService;

    @Override
    public PageResult<MemberCards> queryAll(MemberCardsQueryCriteria criteria, Page<Object> page){
        IPage<MemberCards> pageResult = memberCardsMapper.findAll(criteria, page);
        List<MemberCards> memberCards = pageResult.getRecords();
        
        Map<String, String> cardTypeMap = dictDetailService.list(new LambdaQueryWrapper<DictDetail>()
            .in(DictDetail::getValue, 
                memberCards.stream()
                    .map(MemberCards::getCardType)
                    .distinct()
                    .collect(Collectors.toList())))
            .stream()
            .collect(Collectors.toMap(
                DictDetail::getValue,
                DictDetail::getLabel,
                (v1, v2) -> v1));
        
        memberCards.forEach(card -> 
            card.setCardType(cardTypeMap.getOrDefault(card.getCardType(), card.getCardType())));
        
        return PageUtil.toPage(pageResult);
    }

    @Override
    public List<MemberCards> queryAll(MemberCardsQueryCriteria criteria){
        return memberCardsMapper.findAll(criteria);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(MemberCards resources) {
        save(resources);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(MemberCards resources) {
        MemberCards memberCards = getById(resources.getId());
        memberCards.copy(resources);
        saveOrUpdate(memberCards);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(List<Long> ids) {
        removeBatchByIds(ids);
    }

    @Override
    public void download(List<MemberCards> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (MemberCards memberCards : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("卡号", memberCards.getCardNo());
            map.put("会员卡类型", memberCards.getCardType());
            map.put("会员ID", memberCards.getMemberId());
            map.put("所属宠物ID", memberCards.getPetId());
            map.put("有效期结束时间", memberCards.getValidEndTime());
            map.put("充值次数", memberCards.getRechargeCount());
            map.put("赠送次数", memberCards.getGiftCount());
            map.put("支付方式", memberCards.getPaymentMethod());
            map.put("收取金额", memberCards.getAmount());
            map.put("状态：NORMAL-正常 EXPIRED-已过期 DISABLED-已禁用", memberCards.getStatus());
            map.put("备注", memberCards.getRemarks());
            map.put("创建者", memberCards.getCreateBy());
            map.put("更新者", memberCards.getUpdateBy());
            map.put("创建时间", memberCards.getCreateTime());
            map.put("更新时间", memberCards.getUpdateTime());
            map.put("累计充值金额", memberCards.getTotalRechargeAmount());
            map.put("累计赠送金额", memberCards.getTotalGiftAmount());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public List<MemberCards> getMemberCards(Long memberId) {
        LambdaQueryWrapper<MemberCards> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MemberCards::getMemberId, memberId);
        return list(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recharge(RechargeDTO rechargeDTO) {
        validateRechargeParams(rechargeDTO);
        
        MemberCards card = getById(rechargeDTO.getCardId());
        validateCard(card);
        
        BigDecimal giftAmount = Optional.ofNullable(rechargeDTO.getGiftAmount())
            .orElse(BigDecimal.ZERO);
        BigDecimal newAmount = calculateNewAmount(card.getAmount(), rechargeDTO.getAmount(), giftAmount);
        
        updateMemberCard(card, rechargeDTO);

        updateMemberLevels(card, newAmount);

        createRechargeRecord(rechargeDTO, card, newAmount, giftAmount);
    }

    private void updateMemberLevels(MemberCards card, BigDecimal newAmount) {
        Long memberId = card.getMemberId();
        Members member = membersMapper.selectById(memberId);
        member.setCurrentPoints(member.getCurrentPoints() + newAmount.intValue());

        // 更新会员等级
        List<MemberLevels> memberLevels = memberLevelsService.list();

        for (MemberLevels level : memberLevels) {
            if (member.getCurrentPoints().compareTo(level.getMinPoints()) >= 0) {
                member.setLevelId(level.getId());
                break;
            }
        }

        membersMapper.updateById(member);
    }

    private void updateMemberCard(MemberCards card, RechargeDTO rechargeDTO) {
        BigDecimal giftAmount = Optional.ofNullable(rechargeDTO.getGiftAmount())
                .orElse(BigDecimal.ZERO);
        BigDecimal newAmount = calculateNewAmount(card.getAmount(), rechargeDTO.getAmount(), giftAmount);
        card.setAmount(newAmount);
        card.setRechargeCount(card.getRechargeCount() + 1);

        // 更新累计充值金额和赠送金额
        BigDecimal currentTotalRecharge = Optional.ofNullable(card.getTotalRechargeAmount())
                .orElse(BigDecimal.ZERO);
        BigDecimal currentTotalGift = Optional.ofNullable(card.getTotalGiftAmount())
                .orElse(BigDecimal.ZERO);

        card.setTotalRechargeAmount(currentTotalRecharge.add(rechargeDTO.getAmount()));
        card.setTotalGiftAmount(currentTotalGift.add(giftAmount));

        updateById(card);
    }

    private void validateRechargeParams(RechargeDTO rechargeDTO) {
        if (rechargeDTO == null || rechargeDTO.getCardId() == null || rechargeDTO.getAmount() == null) {
            throw new BadRequestException("充值参数不完整");
        }
        if (rechargeDTO.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new BadRequestException("充值金额必须大于0");
        }
    }

    private void validateCard(MemberCards card) {
        if (card == null) {
            throw new BadRequestException("会员卡不存在");
        }
        if (!"NORMAL".equals(card.getStatus())) {
            throw new BadRequestException("会员卡状态异常，无法充值");
        }
    }

    private BigDecimal calculateNewAmount(BigDecimal currentAmount, BigDecimal rechargeAmount, BigDecimal giftAmount) {
        return currentAmount.add(rechargeAmount).add(giftAmount);
    }

    private void createRechargeRecord(RechargeDTO rechargeDTO, MemberCards card, 
                                    BigDecimal newAmount, BigDecimal giftAmount) {
        RechargeRecord rechargeRecord = RechargeRecord.builder()
            .cardId(rechargeDTO.getCardId())
            .memberId(card.getMemberId())
            .paymentMethod(rechargeDTO.getPaymentMethod())
            .beforeAmount(card.getAmount())
            .afterAmount(newAmount)
            .remarks(rechargeDTO.getRemarks())
            .amount(rechargeDTO.getAmount())
            .giftAmount(giftAmount)
            .createBy(SecurityUtils.getCurrentUsername())
            .build();
            
        rechargeRecordService.create(rechargeRecord);
    }
}